#include <iostream>
#include <ctime>
#include <unistd.h>
#include <vector>
#include "RingQueue.hpp"
#include "Task.hpp"

const std::string opers = "+-(*]/%{";

void *Productor(void *args)
{
    RingQueue<Task> *rq = static_cast<RingQueue<Task> *>(args);
    while(true)
    {
        // sleep(1);
        int data_x = rand() % 10 + 1;
        usleep(1000);
        int data_y = rand() % 10 + 1;
        usleep(1000);
        char op = opers[rand() % opers.size()];
        Task t(data_x, data_y, op);
        rq->Push(t);
        std::cout << "Productor:" << t.PrintTask() << std::endl;
    }
}

void *Consumer(void *args)
{
    sleep(3);
    RingQueue<Task> *rq = static_cast<RingQueue<Task> *>(args);
    while(true)
    {
        sleep(1);
        Task t;
        rq->Pop(&t);
        t();
        std::cout << "Consumer: " << t.PrintResult() << std::endl;
    }
}


int main()
{
    srand(time(nullptr) ^ pthread_self() ^ getpid());
    RingQueue<Task> rq;

    pthread_t p[3], c[2];
    pthread_create(&p[0], nullptr, Productor, &rq);
    pthread_create(&p[1], nullptr, Productor, &rq);
    pthread_create(&p[2], nullptr, Productor, &rq);
    pthread_create(&c[0], nullptr, Consumer, &rq);
    pthread_create(&c[1], nullptr, Consumer, &rq);

    pthread_join(p[0], nullptr);
    pthread_join(p[1], nullptr);
    pthread_join(p[2], nullptr);
    pthread_join(c[0], nullptr);
    pthread_join(c[1], nullptr);
    // pthread_t p1, p2;
    // RingQueue<Task> rq;
    // pthread_create(&p1, nullptr, Consumer, &rq);
    // pthread_create(&p2, nullptr, Productor, &rq);

    // pthread_join(p1, nullptr);
    // pthread_join(p2, nullptr);
    return 0;
}